package com.demo.file.controller;


import cn.hutool.core.thread.ThreadUtil;
import com.demo.file.entity.SegmentFile;
import com.demo.file.service.ISegmentFileService;
import com.demo.file.vo.R;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

/**
 * 前端控制器
 *
 * @author alyy20
 * @since 2022-04-18
 */
@Slf4j
@Controller
@RequestMapping("/file")
public class SegmentFileController {

    @Autowired
    ISegmentFileService segmentFileService;

    @Value("${file.save-path}")
    private String savePath;

    @RequestMapping("/index")
    public String index() {
        return "/index";
    }

    @RequestMapping("/upload")
    public String upload() {
        return "/pages/upload.html";
    }

    /**
     * 上传文件需要从前端取分片序号和分片大小，因为切割是前端切滴，所以文件原始大小也要返回来
     * 剩余信息在service中计算
     * 首先确认是否存在该文件，不存在就放到数据库中新建
     * 之后对segmentIndex分别处理，存储分片文件（文件分片前端完成）
     * 简化情况，认为前端都是异步请求，并且分片是按顺序请求的，只有前面的index处理了才能处理后面的分片（在前端体现）
     * 这样当segmentIndex和总count相同时，获取结果
     *
     * @param file
     * @param originFileName
     * @param fileSize
     * @param segmentIndex
     * @param segmentSize
     * @param key
     * @return
     * @throws JsonProcessingException
     */
    @ResponseBody
    @RequestMapping("/segmentUpload")
    public R segmentUploadFile(MultipartFile file, String originFileName, Integer fileSize, Integer segmentIndex, Integer segmentSize, String key) throws JsonProcessingException {
        SegmentFile segmentFile = segmentFileService.checkFile(key);
        if (segmentFile == null) {
            boolean writeSuccess = segmentFileService.createFile(originFileName, savePath, fileSize, segmentSize, key);
            if (!writeSuccess) {
                return R.fail("文件数据库记录创建失败");
            }
        }
        segmentFile = segmentFileService.checkFile(key);

        /**
         * 存入当前分片
         */
        boolean segmentWriteSuccess = segmentFileService.saveFile(file, savePath, key, originFileName, segmentIndex);
        if (!segmentWriteSuccess) {
            return R.fail("分片存储失败");
        }
        segmentFile.setSegmentIndex(segmentIndex);
        boolean isUpdateSuccess = segmentFileService.modify(segmentFile);
        if (!isUpdateSuccess) {
            return R.fail("文件数据库记录更新失败");
        }

        /**
         * 分片文件全部上传完成开始合并
         */
        if (segmentIndex.intValue() == segmentFile.getSegmentTotal().intValue()) {
            boolean mergeSuccess = segmentFileService.mergeSegment(key);
            if (mergeSuccess) {
                ThreadUtil.execute(() -> {
                    try {
                        segmentFileService.deleteSegments(key);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                });
                return R.ok(segmentFile);
            } else {
                return R.fail("文件合并失败");
            }
        }
        return R.ok(segmentFile);
    }

    /**
     * 检查文件是否存在
     *
     * @param key
     * @return
     * @throws JsonProcessingException
     */
    @ResponseBody
    @RequestMapping("/checkFile")
    public R checkFileExist(String key) {
        SegmentFile segmentFile = segmentFileService.checkFile(key);
        if (segmentFile == null) {
            return R.fail("该文件未上传");
        } else {
            return R.ok(segmentFile);
        }
    }
}
